home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 2261 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  4.6 KB

  1. Path: mail2news.demon.co.uk!genesis.demon.co.uk
  2. From: Lawrence Kirby <fred@genesis.demon.co.uk>
  3. Newsgroups: comp.lang.c
  4. Subject: Re: Q: realloc->free?
  5. Date: Sat, 20 Jan 96 02:08:34 GMT
  6. Organization: none
  7. Message-ID: <822103714snz@genesis.demon.co.uk>
  8. References: <4df2ud$706@oxy.rust.net> <4dgic7$qin@unix.sri.com> <dan.821890778@handel> <821904243snz@genesis.demon.co.uk> <dan.821977599@handel>
  9. Reply-To: fred@genesis.demon.co.uk
  10. X-NNTP-Posting-Host: genesis.demon.co.uk
  11. X-Newsreader: Demon Internet Simple News v1.27
  12. X-Mail2News-Path: genesis.demon.co.uk
  13.  
  14. In article <dan.821977599@handel> dan@bristol.com "J. Daniel Smith" writes:
  15.  
  16. >In <821904243snz@genesis.demon.co.uk> Lawrence Kirby <fred@genesis.demon.co.uk>
  17. > writes:
  18. >>[...]
  19. >>>adding code to deal for the extremely rare case can add
  20. >>>significantly to the complexity of the code.
  21. >
  22. >>Adding error checking for heap allocation makes minimal difference to
  23. >>program complexity. OTOH dealing with rare cases properly makes the task
  24. >>of debugging much easier.
  25. >
  26. >Here's an example of what I had in mind
  27. >   void f(const char *string)
  28. >   {
  29. >      static char *buf = NULL;
  30. >
  31. >      buf = realloc(buf, strlen(string) + 1);
  32. >      /* ... do whatever with buf ... */
  33. >   }
  34. >Dealing with the realloc() failure makes this
  35. >   void f(const char *string)
  36. >   {
  37. >      static char *buf = NULL;
  38. >      char *tmp;
  39. >
  40. >      if ((tmp = realloc(buf, strlen(string) + 1)) == NULL)
  41. >        return; /* realloc() failed...now what? */
  42.  
  43. Well, one thing you know you cannot do is simply continue and use the
  44. returned value as if it pointed to valid memory. That road leads to
  45. crashing programs, corrupted data and debugging nightmares.
  46.  
  47. >      buf = tmp;
  48. >      /* ... do whatever with buf ... */
  49. >   }
  50. >This prevents a crash, and in that respect it is definately more
  51. >robust than not checking realloc()'s return value.  But does the
  52. >program still run correctly?  Not likely, since whatever f() was
  53. >supposed to do isn't being done.
  54.  
  55. Clearly of the rest of the program expects f() to have done something
  56. it cannot simply return not having done it.
  57.  
  58. >
  59. >One could make all kinds of arguments about return values, error codes,
  60. >poor software design, whatever.  And I'll agree that things would be
  61. >better if f() were written as follows
  62. >   int f(const char *string)
  63. >   {
  64. >      static char *buf = NULL;
  65. >      char *tmp;
  66. >
  67. >      if ((tmp = realloc(buf, strlen(string) + 1)) == NULL)
  68. >        return 0; /* realloc() failed */
  69. >      buf = tmp;
  70. >      /* ... do whatever with buf ... */
  71. >
  72. >      return 1;
  73. >   }
  74. >but in real life, this sometimes isn't an option.
  75.  
  76. Can you give an example where returning a success condition in some form
  77. or another can't be used?
  78.  
  79. >>> And if realloc() does
  80. >>>fail, there are probably a lot bigger things to worry about than
  81. >>>leaking memory (like the GUI not being able to create a window to tell
  82. >>>you something has went wrong).
  83. >>
  84. >>You can at the very least exit cleanly at the point of failure. If you fail
  85. >>in allocation you can try to creewate an error window and exit cleanly
  86. >>if that fails.
  87. >
  88. >yes, this is nicer than crashing and leaving a core dump, or getting a
  89. >GPF dialog box.  But a GUI application suddenly quitting for no
  90. >apparent reason isn't very nice either.
  91.  
  92. It is much better than it locking up, corrupting the rest of the system or
  93. your data files for no apparent reason. A way can usually be found to
  94. log some sort of diagnostic. A reasonable OS would be able to log events
  95. such as refusing memory allocation to a program. 'Out of memory' is
  96. something tht can usually be corrected relatively simply and the program
  97. rerun.
  98.  
  99. >>>Yes, the programmer needs to be aware of the fact that realloc() can
  100. >>>fail, but in some cases ALWAYS checking the return value of realloc()
  101. >>>just isn't practical given other constraints.
  102. >>
  103. >>I can't think of any reasonable constraints that would make it impractical.
  104. >
  105. >the function above is burried 15 calls deep, many of the functions in
  106. >the call chain have no provisions for checking return values.  As you
  107. >say, calling exit() will at least terminate cleanly, but now I've got
  108. >calls to exit() (or my own fatal_exit()) scattered all through my
  109. >program which some might say is poor style.
  110.  
  111. Only because proper error handling is better style. This 'poor style' is
  112. still a vastly better style than not checking for error conditions at all.
  113.  
  114. >My only real contention is with "ALWAYS" - I don't like absolutes. :-)
  115.  
  116. I think this is one you should learn to love! :-)
  117.  
  118. -- 
  119. -----------------------------------------
  120. Lawrence Kirby | fred@genesis.demon.co.uk
  121. Wilts, England | 70734.126@compuserve.com
  122. -----------------------------------------
  123.